from maix import camera, display, image, nn, app, pinmap, time, uart, touchscreen

'''
协议
检测到最开始的目标药房号：0x0a 0x0b 0x01 target 0x0c
在路上检测到的目标药房号：0x0a 0x0b 0x02 (0x00:L、0x01:R) 0x0c
识别到停车点：           0x0a 0x0b 0x03 0x00 0x0c
'''
#************************************************************
target = 0      # 目标药房
L = 0           # 左转向
R = 1           # 右转向
direction = 2   # 转向标志
max_count = 10  # 滤波系数
min_count = 8
count = 0       # 计数
blobs_quantity = 0  # 记录块的数量
number_list = list(range(max_count))                # 保存每次识别的结果
tinydict = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0} # 保存每个数字对应的出现次数
#************************************************************
# 初始化串口
device = "/dev/ttyS0"
serial0 = uart.UART(device, 115200)
# 加载模型
detector = nn.YOLOv5(model="/root/models/model-120311(number)/model_120311.mud", dual_buff=True)
# 打开摄像头并显示
cam = camera.Camera(680, 480, detector.input_format())
dis = display.Display()
# 初始化按键扫描对象
ts = touchscreen.TouchScreen()
exit_label = "X"
size = image.string_size(exit_label)
exit_btn_pos = [620, 0, 60, 60]
exit_btn_disp_pos = image.resize_map_pos(cam.width(), cam.height(), dis.width(), dis.height(), image.Fit.FIT_CONTAIN, exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3])


# 显示屏显示数据
def display_data(img):
    global target,direction,L,R,blobs_quantity
    # 显示参数
    img.draw_string(0,2,"Target:{}".format(target),color = image.COLOR_RED,scale=2)
    if direction == L:
        img.draw_string(0,22,"Direction:L",color = image.COLOR_BLUE,scale=2)
    elif direction == R:
        img.draw_string(0,22,"Direction:R",color = image.COLOR_BLUE,scale=2)
    img.draw_string(0,44,"blobs:{}".format(blobs_quantity),color = image.COLOR_GREEN,scale=2)
    img.draw_string(0,88,"max_count:{}".format(max_count),color = image.COLOR_GREEN,scale=2)
    img.draw_string(0,110,"min_count:{}".format(min_count),color = image.COLOR_GREEN,scale=2)
    # 画按键
    img.draw_string(exit_btn_pos[0], exit_btn_pos[1], exit_label, image.COLOR_WHITE,scale=4)
    img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3],  image.COLOR_WHITE, 2)

def Update_parament():
    global target,max_count,min_count,count,number_list,direction
    target = 0      
    max_count = 10
    min_count = 8
    count = 0
    direction = 2   
    number_list = list(range(max_count)) 


# 按键检测
def is_in_button(x, y, btn_pos):
    return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3]
def Key_scan():
    x, y, pressed = ts.read()
    if is_in_button(x, y, exit_btn_disp_pos) and pressed == 1:
        # 系数重置
        Update_parament()

# 获取中心点坐标
def Get_center_point(x,y,w,h):
    return [x+w//2,y+h//2]

# 串口发送
def Usart_send(command):
    data = [0x0a,0x0b]
    for c in command:
        data.append(c)
    data.append(0x0c)
    serial0.write(bytes(data))
    #print(data)

# 查看停车点
def detect_stop_site(img):
    global target,blobs_quantity
    thresholds = [[0, 15, -9, 11, -12, 8]]
    if target != 0:
        ROI = [cam.width()//5, cam.height()//2, cam.width()//5*3, cam.height()//2]
        img.draw_rect(ROI[0],ROI[1],ROI[2],ROI[3], color = image.COLOR_RED)
        blobs = img.find_blobs(thresholds, pixels_threshold=100,roi=ROI)
        for blob in blobs:
            #if blob.pixels() <   # 待定
            img.draw_rect(blob[0], blob[1], blob[2], blob[3], image.COLOR_GREEN)
        blobs_quantity = len(blobs)
        if blobs_quantity > 6:  # 发送停车指令
            for i in range(0,5):
                Usart_send([0x03,0x00])
                time.sleep_ms(10)
            Update_parament()
    else :
        blobs_quantity = 0

# 识别数字
def detector_number(img):
    global target,cam,direction,L,R,count,number_list,max_count,min_count
    objs = detector.detect(img, conf_th = 0.6, iou_th = 0.45) # conf_th:置信度
    number = 0
    number_lis = []
    for obj in objs:
        img.draw_rect(obj.x, obj.y, obj.w, obj.h, color = image.COLOR_RED)
        msg = f'{detector.labels[obj.class_id]}: {obj.score:.2f}'
        img.draw_string(obj.x, obj.y, msg, color = image.COLOR_RED)
        msg = f'area:{obj.w*obj.h}'
        img.draw_string(obj.x, obj.y+20, msg, color = image.COLOR_RED)
        number_lis.append(obj)
    number_list[count] = number_lis
    count+=1
    if count >= max_count:
        count = 0
        # 字典计算数字出现次数
        tinydict = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0}
        tinydict_coor = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0}
        for number_l in number_list:
            for n in number_l:
                if 'eight'   in detector.labels[n.class_id]:
                    number = 8
                elif 'seven' in detector.labels[n.class_id]:
                    number = 7
                elif 'six'   in detector.labels[n.class_id]:
                    number = 6
                elif 'five'  in detector.labels[n.class_id]:
                    number = 5
                elif 'four'  in detector.labels[n.class_id]:
                    number = 4
                elif 'three' in detector.labels[n.class_id]:
                    number = 3
                elif 'two'   in detector.labels[n.class_id]:
                    number = 2
                elif 'one'   in detector.labels[n.class_id]:
                    number = 1
                tinydict[number]+=1
                tinydict_coor[number] = n   # 记录坐标
        # 字典转换成列表第二列为数字出现次数，根据第二列排序
        '''
        number_list = tinydict.items()
        number_list = sorted(number_list, key=lambda x: x[1], reverse=True)
        print(number_list)
        '''
        #print(tinydict)
        for key in tinydict.keys():
            if tinydict[key] > min_count:
                if target == 0:
                    target = key
                    max_count = 6  # 同时降低滤波系数
                    min_count = 3
                    for i in range(0,5):
                        Usart_send([0x01,target])
                        time.sleep_ms(10)
                else :
                    if key == target:
                        center = Get_center_point(tinydict_coor[key].x,tinydict_coor[key].y,tinydict_coor[key].w,tinydict_coor[key].h)
                        if center[0] < cam.width()//2:  # L
                            direction = L
                        else:   # R
                            direction = R
                        Usart_send([0x02,direction])
        number_list = list(range(max_count)) # 初始化列表

while not app.need_exit():
    img = cam.read()
    detector_number(img)        # 识别数字
    detect_stop_site(img)       # 查找停车点
    Key_scan()                  # 按键检测
    display_data(img)           # 显示数据
    dis.show(img)
